const { muser } = require('../../models/system/muser');
const { role } = require('../../models/system/mrole');
const bcrypt = require('bcryptjs');
const { easyCopy } = require("../../utils/utils");
const { sign } = require('../../utils/auth');
const { PASSWORD } = require('../../config/constants');
const logger = require('../../utils/logger');

class UserService {
    static async checkUsernameExist(username) {
        try {
            if (!username) {
                throw new Error('用户名不能为空');
            }
            return muser.findOne({ username });
        } catch (error) {
            logger.error(`检查用户名存在性失败: ${error.message}, 用户名: ${username}`);
            throw new Error(`检查用户名存在性失败: ${error.message}`);
        }
    }
    
    static async updateUserMoney(userId, money) {
        try {
            if (!userId) {
                throw new Error('用户ID不能为空');
            }
            
            if (typeof money !== 'number') {
                throw new Error('金额必须是数字');
            }
            
            const result = await muser.findOneAndUpdate(
                { _id: userId },
                { $inc: { money } },
                { new: true }
            );
            
            if (!result) {
                throw new Error('用户不存在');
            }
            
            logger.info(`成功更新用户余额: ${userId}, 金额变化: ${money}`);
            return result;
        } catch (error) {
            logger.error(`更新用户余额失败: ${error.message}, 用户ID: ${userId}, 金额: ${money}`);
            throw new Error(`更新用户余额失败: ${error.message}`);
        }
    }
    
    //给用户加入优惠券使用记录
    static async addUserCouponRecord(userId, couponId, usedCount = 1) {
        try {
            if (!userId || !couponId) {
                throw new Error('用户ID和优惠券ID不能为空');
            }
            
            if (typeof usedCount !== 'number' || usedCount <= 0) {
                throw new Error('使用次数必须是正整数');
            }
            
            const result = await muser.findOneAndUpdate(
                { _id: userId },
                { $push: { usedCoupons: { couponId, usedCount } } },
                { upsert: true, new: true }
            );
            
            if (!result) {
                throw new Error('用户不存在');
            }
            
            logger.info(`成功添加用户优惠券记录: ${userId}, 优惠券ID: ${couponId}, 使用次数: ${usedCount}`);
            return result;
        } catch (error) {
            logger.error(`添加用户优惠券记录失败: ${error.message}, 用户ID: ${userId}, 优惠券ID: ${couponId}`);
            throw new Error(`添加用户优惠券记录失败: ${error.message}`);
        }
    }


    static async createUser(userData) {
        try {
            if (!userData) {
                throw new Error('用户数据不能为空');
            }

            // 验证必需字段
            if (!userData.username) {
                throw new Error('用户名不能为空');
            }

            // 用户名格式验证
            if (typeof userData.username !== 'string' || userData.username.length < 3 || userData.username.length > 30) {
                throw new Error('用户名长度必须在3到30个字符之间');
            }

            // 检查用户名是否已存在
            const existingUser = await this.checkUsernameExist(userData.username);
            if (existingUser) {
                throw new Error('用户名已存在');
            }

            // 验证手机号格式（如果提供）
            if (userData.phone && !/^1[3-9]\d{9}$/.test(userData.phone)) {
                throw new Error('手机号格式不正确');
            }

            // 验证邮箱格式（如果提供）
            if (userData.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(userData.email)) {
                throw new Error('邮箱格式不正确');
            }

            // 密码加密
            const passwordToHash = userData.password || PASSWORD.DEFAULT;
            // 密码长度验证
            if (passwordToHash.length < 6 || passwordToHash.length > 128) {
                throw new Error('密码长度必须在6到128个字符之间');
            }
            const hashedPassword = await bcrypt.hash(passwordToHash, PASSWORD.SALT_ROUNDS);
            userData.password = hashedPassword;

            const newUser = new muser(userData);
            const savedUser = await newUser.save();
            
            logger.info(`用户创建成功: ${savedUser.username}`);
            return easyCopy(savedUser);
        } catch (error) {
            logger.error(`用户创建失败: ${error.message}`);
            throw new Error(`用户创建失败: ${error.message}`);
        }
    }

    static async updateUser(userId, userData) {
        try {
            if (!userId || !userData) {
                throw new Error('用户ID和用户数据不能为空');
            }

            // 验证用户名格式（如果提供）
            if (userData.username) {
                if (typeof userData.username !== 'string' || userData.username.length < 3 || userData.username.length > 30) {
                    throw new Error('用户名长度必须在3到30个字符之间');
                }
                
                // 检查用户名是否已存在
                const existingUser = await this.checkUsernameExist(userData.username);
                if (existingUser && existingUser._id.toString() !== userId) {
                    throw new Error('用户名已存在');
                }
            }

            // 验证手机号格式（如果提供）
            if (userData.phone && !/^1[3-9]\d{9}$/.test(userData.phone)) {
                throw new Error('手机号格式不正确');
            }

            // 验证邮箱格式（如果提供）
            if (userData.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(userData.email)) {
                throw new Error('邮箱格式不正确');
            }

            const result = await muser.findOneAndUpdate(
                { _id: userId },
                { $set: userData },
                { new: true }
            );
            
            if (!result) {
                throw new Error('用户不存在');
            }
            
            logger.info(`成功更新用户: ${userId}`);
            return result;
        } catch (error) {
            logger.error(`更新用户失败: ${error.message}, 用户ID: ${userId}`);
            throw new Error(`更新用户失败: ${error.message}`);
        }
    }

    static async resetPassword(id, oldPassword, newPassword) {
        try {
            if (!id || !oldPassword || !newPassword) {
                throw new Error('用户ID、旧密码和新密码都不能为空');
            }

            // 添加密码复杂度和长度检查
            if (newPassword.length < 6 || newPassword.length > 128) {
                throw new Error('新密码长度必须在6到128个字符之间');
            }

            const user = await muser.findById(id);
            if (!user) throw new Error('用户不存在');

            const isOldPasswordValid = await bcrypt.compare(oldPassword, user.password);
            if (!isOldPasswordValid) throw new Error('旧密码不正确');

            // 检查新密码是否与旧密码相同
            const isNewPasswordSameAsOld = await bcrypt.compare(newPassword, user.password);
            if (isNewPasswordSameAsOld) {
                throw new Error('新密码不能与旧密码相同');
            }

            const hashedNewPassword = await bcrypt.hash(newPassword, PASSWORD.SALT_ROUNDS);
            user.password = hashedNewPassword;
            await user.save();

            logger.info(`用户密码重置成功: ${user.username}`);
            return { success: true, message: '密码重置成功' };
        } catch (error) {
            logger.error(`用户密码重置失败: ${error.message}, 用户ID: ${id}`);
            throw new Error(`密码重置失败: ${error.message}`);
        }
    }

    static async getUserById(userId) {
        try {
            if (!userId) {
                throw new Error('用户ID不能为空');
            }
            
            const result = await muser.findOne({ _id: userId });
            
            if (!result) {
                throw new Error('用户不存在');
            }
            
            return result;
        } catch (error) {
            logger.error(`获取用户失败: ${error.message}, 用户ID: ${userId}`);
            throw new Error(`获取用户失败: ${error.message}`);
        }
    }

    static async deleteUser(userId) {
        try {
            if (!userId) {
                throw new Error('用户ID不能为空');
            }
            
            const result = await muser.findOneAndDelete({ _id: userId });
            
            if (!result) {
                throw new Error('用户不存在');
            }
            
            logger.info(`成功删除用户: ${userId}`);
            return result;
        } catch (error) {
            logger.error(`删除用户失败: ${error.message}, 用户ID: ${userId}`);
            throw new Error(`删除用户失败: ${error.message}`);
        }
    }

    static async getUserInfo(userId) {
        try {
            if (!userId) {
                throw new Error('用户ID不能为空');
            }
            
            const result = await muser.findOne({ _id: userId }).populate({
                path: 'roles',
                select: 'name btnroles',
                populate: {
                    path: 'roles',
                    model: 'menu',
                    select: 'name alias'
                }
            }).lean();
            
            if (!result) {
                throw new Error('用户不存在');
            }
            
            return result;
        } catch (error) {
            logger.error(`获取用户信息失败: ${error.message}, 用户ID: ${userId}`);
            throw new Error(`获取用户信息失败: ${error.message}`);
        }
    }

    static async authenticate(username, password) {
        try {
            if (!username || !password) {
                throw new Error('用户名和密码不能为空');
            }
            
            // 限制密码长度，防止潜在的DoS攻击
            if (password.length > 128) {
                throw new Error('密码长度不能超过128个字符');
            }
            
            const user = await muser.findOne({ username });
            if (!user) throw new Error('用户不存在');
            if (user.disabled) throw new Error('该账户已被禁用');

            const isPasswordValid = await bcrypt.compare(password, user.password);
            if (!isPasswordValid) throw new Error('密码不正确');

            const token = sign({ id: user._id });
            const roles = await this.getRolesByIds(user.roles);
            const userData = easyCopy(user);
            userData.roles = roles;
            delete userData.password;

            logger.info(`用户认证成功: ${username}`);
            return { userinfo: userData, token };
        } catch (error) {
            logger.error(`用户认证失败: ${error.message}, 用户名: ${username}`);
            throw new Error(`用户认证失败: ${error.message}`);
        }
    }

    static async getUserRoles(userId) {
        try {
            if (!userId) {
                throw new Error('用户ID不能为空');
            }
            
            const result = await muser.findOne({ _id: userId }).populate({
                path: 'roles',
                select: 'name order disabled btnroles',
                populate: {
                    path: 'roles',
                    model: 'menu',
                    select: 'name path disabled isMenu order parentId'
                }
            }).sort({ order: 1 }).lean();
            
            if (!result) {
                throw new Error('用户不存在');
            }
            
            return result;
        } catch (error) {
            logger.error(`获取用户角色失败: ${error.message}, 用户ID: ${userId}`);
            throw new Error(`获取用户角色失败: ${error.message}`);
        }
    }



    static async getUserList({ pageNum = 1, pageSize = 10 }, data) {
        try {
            const query = {
                ...data
            };
            const skip = (pageNum - 1) * pageSize;
            const limit = pageSize;
            const total = await muser.countDocuments(query);
            const userList = await muser.find(query).skip
                (skip).limit(limit).populate({ path: 'roles', select: 'name' }).lean();
            return {
                total,
                page: +pageNum,
                totalPages: Math.ceil(total / pageSize),
                list: userList
            };
        } catch (error) {
            logger.error(`获取用户列表失败: ${error.message}`);
            throw new Error(`获取用户列表失败: ${error.message}`);
        }
    }

    static async getRoleById(roleId) {
        try {
            if (!roleId) {
                throw new Error('角色ID不能为空');
            }
            
            const result = await role.findOne({ _id: roleId }).lean();
            
            if (!result) {
                throw new Error('角色不存在');
            }
            
            return result;
        } catch (error) {
            logger.error(`获取角色失败: ${error.message}, 角色ID: ${roleId}`);
            throw new Error(`获取角色失败: ${error.message}`);
        }
    }

    static async getRolesByIds(roleIds) {
        try {
            if (!Array.isArray(roleIds) || roleIds.length === 0) {
                return [];
            }
            
            const roles = await role.find({ _id: { $in: roleIds } }).populate('roles').lean();
            return roles.map(e => e.name);
        } catch (error) {
            logger.error(`获取角色列表失败: ${error.message}`);
            throw new Error(`获取角色列表失败: ${error.message}`);
        }
    }
}

module.exports = UserService;
